#include <physics/Fixture.h>
#include <physics/ValueLoader.h>
#include <Box2D/Dynamics/b2Body.h>
#include <Box2D/Dynamics/b2Fixture.h>
#include <Box2D/Collision/Shapes/b2Shape.h>

namespace physics
{

#pragma region FixtureLoader

	class FixtureDefLoader: public xml::ObjectANSI
	{
		std::auto_ptr <b2FixtureDef> fixtureDef;

		bool on_node(xml::Provider *prov, const std::string &name)
		{
			if(name == "Density")
				return ValueReader::Read(prov, fixtureDef->density);
			if(name == "Friction")
				return ValueReader::Read(prov, fixtureDef->friction);
			if(name == "Restitution")
				return ValueReader::Read(prov, fixtureDef->restitution);
			if(name == "IsSensor")
				return ValueReader::Read(prov, fixtureDef->isSensor);
			if(name == "Group")
				return ValueReader::Read(prov, fixtureDef->filter.groupIndex);

			return false;
		}

	public:
		FixtureDefLoader(): fixtureDef(new b2FixtureDef()) {}

		std::auto_ptr <b2FixtureDef> GetFixtureDef() { return fixtureDef; }
	};

#pragma endregion

Fixture::Fixture()
{
}

Fixture::~Fixture()
{
}

bool Fixture::ParseFixtureDef(xml::Provider *prov, std::auto_ptr <b2FixtureDef> *fixtureDef)
{
	FixtureDefLoader fixtureDefLoader;
	if(!prov->parse_object(&fixtureDefLoader))
		return false;

	(*fixtureDef) = fixtureDefLoader.GetFixtureDef();
	return true;
}

void Fixture::MakeSensor()
{
	for(b2Fixture *it = body->GetFixtureList(); it != NULL; it = it->GetNext())
		it->SetSensor(true);
}
	
void Fixture::DisableSensor()
{
	for(b2Fixture *it = body->GetFixtureList(); it != NULL; it = it->GetNext())
		it->SetSensor(false);
}
	
bool Fixture::IsSensor()
{
	return body->GetFixtureList()->IsSensor();
}
	
void Fixture::SetCollisionGroup(int groupID)
{
	for(b2Fixture *it = body->GetFixtureList(); it != NULL; it = it->GetNext())
	{
		// change group ID
		b2Filter filter = it->GetFilterData();
		filter.groupIndex = groupID;
		it->SetFilterData(filter);
	}
}
	
int Fixture::GetCollisionGroup() const
{
	return body->GetFixtureList()->GetFilterData().groupIndex;
}

void Fixture::SetFriction(float friction)
{
	for(b2Fixture *it = body->GetFixtureList(); it != NULL; it = it->GetNext())
		it->SetFriction(friction);
}

float Fixture::GetFriction() const
{
	return body->GetFixtureList()->GetFriction();
}
	
void Fixture::SetRestitution(float restitution)
{
	for(b2Fixture *it = body->GetFixtureList(); it != NULL; it = it->GetNext())
		it->SetRestitution(restitution);
}
	
float Fixture::GetRestitution() const
{
	return body->GetFixtureList()->GetRestitution();
}

void Fixture::SetDensity(float density)
{
	for(b2Fixture *it = body->GetFixtureList(); it != NULL; it = it->GetNext())
		it->SetDensity(density);
}

float Fixture::GetDensity() const
{
	return body->GetFixtureList()->GetDensity();
}

}